package mmc.server.shell;

public class ShellUnitTest {

	public static void testSafe(){
		try{
			execute();
		}catch(Exception e){
			e.printStackTrace(System.out);
		}
	}
	
    public static void execute() throws ShellException{
    	test("assert(1)");
    	
    	doAssociativePropertyTest();
    	doAutoBoxingTest();
    	doClassTest();
    	doClassMemberReferenceTest();
    	doOperatorsTest();
    	doStringQuotingTest();
    	doVariableTest();
    	doPriorityTest();
    	doFunTest();
    	
    	System.out.println("All tests passed successfully!");
    }
    
    public static void test(String s) throws ShellException{
    	Shell.getOperationTreeFor(s).executeDefault();
    }
    
    public static void doAssociativePropertyTest() throws ShellException{
    	//right associative
    	test("assert(Math.abs(4^3^2-4^(3^2))<1e-6)");
    	
    	//left associative
    	test("assert(Math.abs(4/3/2-(4/3)/2)<1e-6)");
    	test("assert(Math.abs(4-3-2-((4-3)-2))<1e-6)");
    }

    public static void doAutoBoxingTest() throws ShellException{
    	//Wrapper->primitive
    	test("assert(new(Boolean,1))");
    	test("assert(new(Byte,1))");
    	test("assert(new(Short,1))");
    	test("assert(new(Integer,1))");
    	test("assert(new(Long,1))");
    	test("assert(new(Character,1))");
    	test("assert(new(Float,1))");
    	test("assert(new(Double,1))");
    	
    	//primitive->Wrapper
    	test("assert(!(new(Boolean,1).compareTo(1)))");
    	test("assert(!(new(Byte,1).compareTo(1)))");
    	test("assert(!(new(Short,1).compareTo(1)))");
    	test("assert(!(new(Integer,1).compareTo(1)))");
    	test("assert(!(new(Long,1).compareTo(1)))");
    	test("assert(!(new(Character,1).compareTo(1)))");
    	test("assert(!(new(Float,1).compareTo(1)))");
    	test("assert(!(new(Double,1).compareTo(1)))");
    }
    
    public static void doClassTest() throws ShellException{
    	test("System==java.lang.System");
    	test("java.util.Collection");
    }
    
    public static void doClassMemberReferenceTest() throws ShellException{
    	//instance
    	test("assert(new(java.awt.Dimension,1,2).width==new(java.awt.Dimension,1,2).getWidth())");
    	
    	//static qualified
    	test("assert(java.lang.Math.abs(java.lang.Math.sin(2*java.lang.Math.PI))<1e-6)");
    	
    	//static non-qualified
    	test("assert(Math.abs(Math.sin(2*Math.PI))<1e-6)");
    	
    	//varargs
    	test("assertEquals(String.format(\"%.0f,%.0f\",1,2),\"1,2\")");
    }
    
    public static void doOperatorsTest() throws ShellException{
    	//=
    	test("v=1");
    	test("assert(v==1)");
    	//+=
    	test("assert((v+=1)==2)");
    	test("assert(v==2)");
    	//-=
    	test("assert((v-=1)==1)");
    	test("assert(v==1)");
    	//+
    	test("assert(1+1==2)");
    	//-
    	test("assert(1-3==-2)");
    	//%
    	test("assert(9%6==3)");
    	//*
    	test("assert(3*6==18)");
    	///
    	test("assert(1/1==1)");
    	//^
    	test("assert(2^10==1024)");
    	//==
    	test("assert(1==1)");
    	test("assert(!(2==1))");
    	test("assert(!(new(Object)==new(Object)))");
    	test("v=new(Object)");
    	test("assert(v==v)");
    	test("assert(1==(1-1e-11))"); //because of this stuff variable names must not start with digits
    	test("assert(1==(1+1e-11))");
    	test("assert(!(1==(1-1e-9)))");
    	test("assert(!(1==(1+1e-9)))");
    	//>
    	test("assert(2>1)");
    	test("assert(!(1>2))");
    	//<
    	test("assert(1<2)");
    	test("assert(!(2<1))");
    	//!
    	test("assert(!!1)");
    	test("assert(1==!0)");
    	test("assert(0==!5)");
    	//v--
    	test("v=10");
    	test("assert(v--==10)");
    	test("assert(v==9)");
    	//--v
    	test("assert(--v==8)");
    	test("assert(v==8)");
    	//v++
    	test("assert(v++==8)");
    	test("assert(v==9)");
    	//++v
    	test("assert(++v==10)");
    	test("assert(v==10)");
    	
    	Shell.environment.remove("v");
    }
    
    public static void doStringQuotingTest() throws ShellException{
    	//\n
    	test("assertEquals(\"\\n\",\"\n\")");
    	//\\
    	test("assertEquals(\"\\\\\",\"\\\\\")");
    	//\t
    	test("assertEquals(\"\\t\",\"\t\")");
    	
    	//,
    	test("assertEquals(\"\",\"\")");
    	//"
    	test("assertEquals(\"\\\"\",\"\\\"\")");
    	test("assert(\"\".intern()==\"\".intern())");
    }
    
    public static void doVariableTest() throws ShellException{
    	test("v=1");
    	test("assert(v==1)");
    	test("v=v=v=v=v=v=v");
    	test("assert(v==1)");
    	test("v=new(Object)");
    	test("assert(v==v)");
    	
    	Shell.environment.remove("v");
    }
    
    public static void doPriorityTest() throws ShellException{
    	//assign > comparison
    	test("v=0==0");
    	test("assert(v==1)");
    	
    	//comparison > line
    	test("v=0==0+1");
    	test("assert(v==0)");
    	
    	//line > point
    	test("v=1-2*3");
    	test("assert(v==-5)");
    	
    	//point > unary
    	test("v=!0*3");
    	test("assert(v==3)");
    	
    	//unary > ref
    	test("assert((!new(Integer,1).SIZE)==0)");
    	
    	Shell.environment.remove("v");
    }
    
    public static void doFunTest() throws ShellException{
    	test("v=0");
    	test("v+++++v");
    	
    	test("Shell.environment.remove(\"v\")");
    }
}
